package com.hsteach.service.myopia;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hsteach.common.core.domain.AjaxResult;
import com.hsteach.common.exception.ServiceException;
import com.hsteach.common.utils.PageUtils;
import com.hsteach.common.utils.SecurityUtils;
import com.hsteach.dao.domain.myopia.*;
import com.hsteach.dao.mapper.MyopiaInfoMapper;
import com.hsteach.dao.mapper.MyopiaMapper;
import com.hsteach.dao.mapper.MyopiaRiskMapper;
import com.hsteach.enums.BooleanEnum;
import com.hsteach.framework.feign.client.xgk.dto.ret.AreaStudentRet;
import com.hsteach.framework.feign.client.xgk.dto.ret.StudentRet;
import com.hsteach.framework.feign.client.xgk.dto.ret.AreaSchoolRet;
import com.hsteach.framework.web.service.AuthService;
import com.hsteach.service.third.XgkService;
import com.hsteach.util.MyopiaExcelUtil;
import com.hsteach.web.controller.myopia.dto.*;
import com.hsteach.web.controller.myopia.vo.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 活动列表Service业务层处理
 *
 * @author lx
 * @date 2023-07-07
 */
@Service
public class MyopiaService extends ServiceImpl<MyopiaMapper, Myopia> {

    @Autowired
    private MyopiaMapper myopiaMapper;


    @Autowired
    private MyopiaInfoService infoService;

    @Autowired
    private MyopiaInfoMapper infoMapper;

    @Autowired
    private MyopiaSchoolMissionService schoolMissionService;

    @Autowired
    private MyopiaMissionService myopiaMissionService;

    @Autowired
    private MyopiaRiskService riskService;

    @Autowired
    private MyopiaRiskMapper myopiaRiskMapper;

    @Autowired
    private XgkService xgkService;

    @Autowired
    private AuthService authService;


    /**
     * 查询学校近视管理列表
     *
     * @param dto
     * @return
     */
    public List<Myopia> selectList(MyopiaListDTO dto) {
        String classId = dto.getClassId();
        try {
            if (StringUtils.isNotBlank(classId)) {
                dto.setClassId(getDptClassId(classId));
            }
        }catch (Exception e){
            throw new ServiceException("参数错误");
        }
        dto.setSchoolId(String.valueOf(SecurityUtils.getAuthInfo().getOrganizeId()));
        return myopiaMapper.selectListBySchoolId(dto);
    }

    private String getDptClassId(String classId){
        if (StringUtils.isNotBlank(classId) && classId.contains("_")){
            return classId.substring(classId.lastIndexOf("_") + 1);
        }
        return classId;
    }

    public List<Myopia> areaList(MyopiaListDTO dto) {
        MyopiaMission mission = myopiaMissionService.getNewMission();
        if (mission == null){
            return new ArrayList<>();
        }
        PageUtils.startPage(dto.getPageNum(),dto.getPageSize());
        dto.setMissionId(mission.getId());
        return myopiaMapper.areaList(dto);
    }

    /**
     * 根据档案id获取详情
     */
    public List<MyopiaInfo> getInfoList(Long id) {
        List<MyopiaInfo> infoList = infoService.getInfoList(id);
        return infoList;
    }


    /**
     * 获取青少年占比
     *
     * @param schoolId
     */
    public List<MyopiaSchoolProportionVO> getSchoolProportion(Long schoolId) {

        List<MyopiaSchoolProportionVO> vos = myopiaMapper.getSchoolProportion(schoolId);
        vos.forEach(vo -> {
            String ratio = getNoSymbolRatio(vo.getHeadCount(), vo.getMyopiaCount());
            vo.setBadnessCount(vo.getMyopiaCount());
            vo.setMyopiaRatio(ratio);
            vo.setBadnessRatio(ratio);
        });
        return vos;
    }

    /**
     * 计算比列
     *
     * @param divisor  总数
     * @param dividend 占比数
     * @return
     */
    private static String getRatio(Integer divisor, Integer dividend) {
        Double ratio = (double) dividend / divisor * 100;
        if (divisor.equals(0)){
            ratio = 0D;
        }
        DecimalFormat df = new DecimalFormat("#0.00");
        return df.format(ratio) + "%";
    }

    /**
     * 计算比列不含百分号
     *
     * @param divisor  总数
     * @param dividend 占比数
     * @return
     */
    private static String getNoSymbolRatio(Integer divisor, Integer dividend) {
        Double ratio = (double) dividend / divisor * 100;
        if (divisor.equals(0)){
            ratio = 0D;
        }
        DecimalFormat df = new DecimalFormat("#0.00");
        return df.format(ratio);
    }

    /**
     * 根据年级获取近视程度
     *
     * @param schoolId
     */
    public List<GradeLevelStatVO> getGradeLevelStat(Long schoolId) {
        return myopiaMapper.getGradeLevelStat(schoolId);
    }

    /**
     * 获取学校近视程度
     *
     * @param schoolId
     */
    public GradeLevelStatVO getSchoolLevelStat(Long schoolId) {
        GradeLevelStatVO vo = myopiaMapper.getSchoolLevelStat(schoolId);
        if (vo != null){
            vo.setHeadCount(vo.getHighMyopia() + vo.getLowMyopia() + vo.getMediumMyopia());
        }
        return vo;
    }

    /**
     * 获取班级近视青少年占比
     *
     * @param schoolId
     */
    public List<MyopiaClassProportionVO> getClassProportion(Long schoolId, Integer pageNum, Integer pageSize) {
        PageUtils.startPage(pageNum, pageSize);
        List<MyopiaClassProportionVO> vos = myopiaMapper.getClassProportion(schoolId);
        vos.forEach(vo -> {
            String ratio = getRatio(vo.getHeadCount(), vo.getMyopiaCount());
            vo.setMyopiaRatio(ratio);
            String correctedRatio = getRatio(vo.getMyopiaCount(), vo.getCorrectedCount());
            vo.setCorrectedRatio(correctedRatio);
            vo.setUncorrectedRatio((100 - Double.parseDouble(correctedRatio.replace("%", ""))) + "%");
        });
        return vos;
    }


//    /**
//     * 获取学校统计信息
//     *
//     * @param
//     */
//    public List<SchoolStatVo> getSchoolCount(MyopiaAreaListDTO dto) {
//        Map<String, String> schoolMap = getSchoolMap();
//        MyopiaMission mission = myopiaMissionService.getNewMission();
//        if (ObjectUtils.isEmpty(mission)){
//            return new ArrayList<>();
//        }
//        PageUtils.startPage(dto.getPageNum(),dto.getPageSize());
//        List<SchoolStatVo> vos = myopiaMapper.getSchoolCount(dto.getName(), mission.getId());
//        vos.forEach(e ->{
//            e.setSchoolName(schoolMap.get(e.getSchoolId()));
//        });
//        return vos;
//    }

    /**
     * 获取学校统计信息
     *
     * @param
     */
    public List<MyopiaSchoolMission> getSchoolCount(MyopiaAreaListDTO dto) {
        MyopiaMission mission = myopiaMissionService.getNewMission();
        if (ObjectUtils.isEmpty(mission)){
            return new ArrayList<>();
        }
        PageUtils.startPage(dto.getPageNum(),dto.getPageSize());
        List<MyopiaSchoolMission> schools = schoolMissionService.list(new LambdaQueryWrapper<MyopiaSchoolMission>()
                .eq(MyopiaSchoolMission::getMissionId, mission.getId())
                .eq(MyopiaSchoolMission::getCensusStatus, BooleanEnum.TRUE.getCode())
                .like(StringUtils.isNotBlank(dto.getName()),MyopiaSchoolMission::getSchoolName, dto.getName()));
        return schools;
    }

    public Map<String, String> getSchoolMap() {
        return authService.getSchool("area")
                .stream()
                .collect(Collectors.toMap(AreaSchoolRet::getId, AreaSchoolRet::getName, (v1, v2) -> v2));
    }


    /**
     * 新增视力档案
     * * @param dto
     */
    @Transactional
    public void add(MyopiaAddDTO dto) {
        if (ObjectUtils.isEmpty(dto) || StringUtils.isAnyEmpty(dto.getIdCard(),dto.getStuCode())) {
            throw new ServiceException("参数异常");
        }
        //查询学生是否存在
        StudentRet student = getStudent(dto.getIdCard(),dto.getStuCode());
        if (student == null) {
            throw new ServiceException("身份证号或学籍号有误");
        }
        Myopia myopia = new Myopia();
        BeanUtils.copyProperties(student,myopia);
        myopia.setSchoolId(SecurityUtils.getAuthInfo().getOrganizeId());
        myopia.setStage(dto.getStage());
        if (!StringUtils.isNumeric(dto.getAge()) || Integer.parseInt(dto.getAge()) > 100) {
            throw new ServiceException("请正确填写年龄");
        }
        myopia.setAge(Integer.parseInt(dto.getAge()));
        myopia.setGrade(student.getGradeName());
        myopia.setId(student.getThirdId());
        myopia.setClassId(getDptClassId(student.getClassId()));
        myopia.setClassName(student.getClassName());
        myopia.setMyopiaLevel(dto.getMyopiaLevel());
        myopia.setOkWearer(dto.getOkWearer());
        myopia.setRectifyMode(dto.getRectifyMode());
        saveOrUpdate(myopia);
        MyopiaInfo info = new MyopiaInfo();
        BeanUtils.copyProperties(dto,info);
        info.setRNakedEyesight(getDouble(dto.getRNakedEyesight()));
        info.setREyeAxial(getDouble(dto.getREyeAxial()));
        info.setREyeRadius(getDouble(dto.getREyeRadius()));
        info.setRRectifyEyesight(getDouble(dto.getRRectifyEyesight()));
        info.setLNakedEyesight(getDouble(dto.getLNakedEyesight()));
        info.setLEyeAxial(getDouble(dto.getLEyeAxial()));
        info.setLEyeRadius(getDouble(dto.getLEyeRadius()));
        info.setLRectifyEyesight(getDouble(dto.getLRectifyEyesight()));
        info.setGrade(student.getGradeName());
        info.setMyopiaId(myopia.getId());
        infoService.save(info);
    }


    public Double getDouble(String str) {
        if (StringUtils.isBlank(str)){
            return null;
        }
        try {
            return Double.parseDouble(str);
        } catch (NumberFormatException e) {
            throw new ServiceException("请正确填写内容：视力，球径，轴向必须为数字类型");
        }
    }
    /**
     * 上传学校普查表
     *
     * @param dto
     */
    @Transactional
    public ResponseEntity importFile(MyopiaInportDto dto) throws Exception {
        MyopiaExcelUtil<MyopiaErrorTemplate> util = new MyopiaExcelUtil<>(MyopiaErrorTemplate.class);
        // 从表格读取数据
        List<MyopiaErrorTemplate> lists = util.importExcel(dto.getFile());
        //校验模板
        util.checkTemplate();
        //查询学校所有学生
        Map<String, StudentRet> studentMap = getStudentMap();

        MyopiaMission mission = myopiaMissionService.getById(dto.getMissionId());
        if (ObjectUtils.isEmpty(mission)) {
            throw new ServiceException("任务已删除");
        }

        MyopiaSchoolMission schoolMission = schoolMissionService.getOne(new LambdaUpdateWrapper<MyopiaSchoolMission>()
                .eq(MyopiaSchoolMission::getMissionId, dto.getMissionId())
                .eq(MyopiaSchoolMission::getSchoolId, SecurityUtils.getAuthInfo().getOrganizeId()));
        if (schoolMission == null) {
            throw new ServiceException("不在任务范围内");
        }

        Integer myopiaCount = 0;
        boolean flag = true;
        Set<Myopia> myopias = new HashSet<>();
        Set<MyopiaInfo> infos = new HashSet<>();

        for (MyopiaErrorTemplate e : lists) {
            Myopia myopia = new Myopia();
            MyopiaInfo info = new MyopiaInfo();
            StudentRet student = studentMap.get(e.getIdCardNo()) == null ?
                    studentMap.get(e.getStuCode()):studentMap.get(e.getIdCardNo());
            if (student == null) {
                e.setError("身份证和学籍id有误");
                flag = false;  // 设置标志为 false，表示后续不再更新
            }
            if (flag) {
                // 更新基本信息
                int okWear = e.getOkWearer().equals("是") ? 1 : 0;
                myopia.setGrade(student.getGradeName());
                myopia.setClassName(student.getClassName());
                myopia.setClassId(getDptClassId(student.getClassId()));
                myopia.setAge(e.getAge());
                myopia.setSex(student.getSex());
                myopia.setName(student.getName());
                myopia.setStage(e.getStage());
                myopia.setMyopiaLevel(e.getMyopiaLevel());
                myopia.setRectifyMode(e.getRectifyMode());
                myopia.setSchoolId(SecurityUtils.getAuthInfo().getOrganizeId());
                myopia.setId(student.getThirdId());
                myopia.setOkWearer(okWear);
                myopias.add(myopia);
                BeanUtils.copyProperties(e, info);
                info.setMyopiaId(myopia.getId());
                info.setMissionName(mission.getName());
                info.setSchoolId(SecurityUtils.getAuthInfo().getOrganizeId());
                info.setMissionId(mission.getId());
                info.setOkWearer(okWear);
                infos.add(info);
            }
            if (flag && !e.getMyopiaLevel().equals("未近视")) {
                myopiaCount++;
            }
        }
        if (!flag) {
            //存在错误导出数据
            return util.exportExcelWorkbook(lists, "普查表", util.getTitle());
        }
        //删除本次任务多次上传，档案数据
        int delCount = infoMapper.delete(new LambdaQueryWrapper<MyopiaInfo>()
                .eq(MyopiaInfo::getMissionId, mission.getId())
                .eq(MyopiaInfo::getSchoolId, SecurityUtils.getAuthInfo().getOrganizeId()));

        saveOrUpdateBatch(myopias);
        infoService.saveBatch(infos);
        //更新学校任务详情
        schoolMission.setStuCount(myopias.size());
        schoolMission.setMyopiaNum(myopiaCount);
        schoolMission.setCensusStatus(1);
        schoolMissionService.updateById(schoolMission);
        //跟新任务
        mission.setStuCount(mission.getStuCount() + infos.size() - delCount);
        myopiaMissionService.updateById(checkStatus(mission, schoolMission,delCount == 0));
        return new ResponseEntity(AjaxResult.success(),HttpStatus.OK);
    }


    //校验状态
    private MyopiaMission checkStatus(MyopiaMission mission, MyopiaSchoolMission schoolMission,Boolean flag) {
        if (schoolMission.getCensusStatus().equals(1) && schoolMission.getRiskStatus().equals(1) && flag) {
            mission.setUpCount(mission.getUpCount() + 1);
            mission.setNupCount(mission.getNupCount() - 1);
            if (mission.getNupCount() == 0) {
                mission.setStatus(1);
            }
        }
        return mission;
    }


    /**
     * 上传学校高危表
     *
     * @param dto
     */
    @Transactional
    public ResponseEntity importRiskFile(MyopiaInportDto dto) throws Exception {
        MyopiaExcelUtil<MyopiaRiskErrorTemplate> util = new MyopiaExcelUtil<>(MyopiaRiskErrorTemplate.class);
        // 从表格读取数据
        List<MyopiaRiskErrorTemplate> lists = util.importExcel(dto.getFile());
        //校验模板
        util.checkTemplate();

        MyopiaMission mission = myopiaMissionService.getById(dto.getMissionId());
        if (mission == null) {
            throw new ServiceException("任务已删除");
        }

        MyopiaSchoolMission schoolMission = schoolMissionService.getOne(new LambdaUpdateWrapper<MyopiaSchoolMission>()
                .eq(MyopiaSchoolMission::getMissionId, dto.getMissionId())
                .eq(MyopiaSchoolMission::getSchoolId, SecurityUtils.getAuthInfo().getOrganizeId()));

        if (ObjectUtils.isEmpty(schoolMission)) {
            throw new ServiceException("不在任务范围内");
        }
        Map<String, StudentRet> studentMap = getStudentMap();

        Set<MyopiaRisk> risks = new HashSet<>();

        boolean flag = true;
        for (MyopiaRiskErrorTemplate e : lists) {
            StudentRet student = studentMap.get(e.getIdCardNo()) == null ?
                    studentMap.get(e.getStuCode()):studentMap.get(e.getIdCardNo());
            if (student == null) {
                e.setError("身份证和学籍id有误");
                flag = false;  // 设置标志为 false，表示后续不再更新
            }
            if (flag) {
                MyopiaRisk risk = new MyopiaRisk();
                risk.setRiskLevel(e.getRiskLevel());
                risk.setMissionId(dto.getMissionId());
                risk.setSchoolId(SecurityUtils.getAuthInfo().getOrganizeId());
                risk.setStuId(student.getThirdId());
                risk.setGrade(student.getGradeName());
                risks.add(risk);
            }
        }
        if (!flag) {
            //存在错误导出数据
            return util.exportExcelWorkbook(lists,"高危表", util.getTitle());
        }
        //删除本次任务多次上传，档案数据
        int delCount = myopiaRiskMapper.delete(new LambdaQueryWrapper<MyopiaRisk>()
                .eq(MyopiaRisk::getMissionId, mission.getId())
                .eq(MyopiaRisk::getSchoolId, SecurityUtils.getAuthInfo().getOrganizeId()));
        riskService.saveBatch(risks);
        //更新学校任务详情
        schoolMission.setRiskNum(risks.size());
        schoolMission.setRiskStatus(1);
        schoolMissionService.updateById(schoolMission);
        //跟新任务
        myopiaMissionService.updateById(checkStatus(mission, schoolMission,delCount == 0));
        return new ResponseEntity(AjaxResult.success(),HttpStatus.OK);
    }

    /**
     * 获取所有学生
     *
     * @return
     */
    private Map<String, StudentRet> getStudentMap() {
        //查询学校所有学生
        Map<String, StudentRet> studentMap = xgkService.getStudentBySchoolId(SecurityUtils.getAuthInfo().getOrgCode(),null)
                .stream()
                .collect(Collectors.toMap(e->StringUtils.isEmpty(e.getIdCardNo())?e.getStuNo():e.getIdCardNo(), StudentRet -> StudentRet, (key1, key2) -> key2));
        return studentMap;
    }

    /**
     * 区域获取所有学生
     *
     * @return
     */
    private Map<String, AreaStudentRet> getAreaStudentMap(String schoolId) {
        //查询学校所有学生
        Map<String, AreaStudentRet> studentMap = authService.getStudentBySchoolId(schoolId)
                .stream()
                .collect(Collectors.toMap(e->StringUtils.isEmpty(e.getIcNumber())?e.getIcNumber():e.getStudentNo(), StudentRet -> StudentRet, (key1, key2) -> key2));
        return studentMap;
    }

    /**
     * 根据idCard获取单个学生
     *
     * @return
     */
    public StudentRet getStudent(String idCardNo,String stuCode) {
        StudentRet student;
        student = xgkService.getStudentBySchoolId(SecurityUtils.getAuthInfo().getOrgCode(),idCardNo)
                .stream()
                .findFirst().orElse(null);
        if (ObjectUtils.isEmpty(student) && StringUtils.isNotEmpty(stuCode)){
            student = xgkService.getStudentByStuCode(SecurityUtils.getAuthInfo().getOrgCode(),stuCode)
                    .stream()
                    .findFirst().orElse(null);
        }
        return student;
    }

    /**
     * 批量删除档案，档案详情
     *
     * @param ids
     */
    @Transactional
    public void batchDel(Long[] ids) {
        //批量删除档案
        List<Long> idList = Arrays.asList(ids);
        myopiaMapper.deleteBatchIds(idList);
        //批量删除档案详情
        infoService.remove(new LambdaQueryWrapper<MyopiaInfo>()
                .in(MyopiaInfo::getMyopiaId, idList));
    }

    /**
     * 获取区域青少年近视占比
     *
     * @param
     */
    public List<MyopiaSchoolProportionVO> getProportion() {
        //获取最新一次的任务
        MyopiaMission mission = myopiaMissionService.getNewMission();
        if (ObjectUtils.isEmpty(mission)){
            return new ArrayList<>();
        }
        List<MyopiaSchoolProportionVO> vos = myopiaMapper.getProportion(mission.getId());
        vos.forEach(vo -> {
            String ratio = getNoSymbolRatio(vo.getHeadCount(), vo.getMyopiaCount());
            vo.setBadnessCount(vo.getMyopiaCount());
            vo.setMyopiaRatio(ratio);
            vo.setBadnessRatio(ratio);
        });
        return vos;
    }

    public List<MyopiaRiskVO> getRiskProportion(Long schoolId) {
        List<MyopiaRiskVO> vo = riskService.getRiskProportion(schoolId);
        return vo;
    }

    public List<GradeLevelStatVO> getStageLevelStat() {
        MyopiaMission mission = myopiaMissionService.getNewMission();
        if (mission == null){
            return new ArrayList<>();
        }
        return myopiaMapper.getStageLevelStat(mission.getId());
    }

    /**
     * 区域获取近视程度
     *
     * @param
     */
    public GradeLevelStatVO getLevelStat() {
        MyopiaMission mission = myopiaMissionService.getNewMission();
        if (mission == null){
            return new GradeLevelStatVO();
        }
        return myopiaMapper.getLevelStat(mission.getId());
    }

    /**
     * 区域高危统计 type1为年级单位 2为学校单位"
     *
     * @param
     * @return
     * @throws Exception
     */
    public List<MyopiaRiskVO> getAreaRiskProportion(Integer type) {
        if (type == null) {
            throw new ServiceException("参数异常");
        }
        List<MyopiaRiskVO> vo = riskService.getAreaRiskProportion(type);
        return vo;
    }

    /**
     * 区域已近视儿童青少年占比3
     *
     * @param
     * @return
     * @throws Exception
     */
    public List<MyopiaClassProportionVO> getAreaProportion(Integer type, Integer pageNum, Integer pageSize) {
        if (type == null) {
            throw new ServiceException("参数异常");
        }
        MyopiaMission newMission = myopiaMissionService.getNewMission();
        if (ObjectUtils.isEmpty(newMission)) {
            return new ArrayList<>();
        }
        PageUtils.startPage(pageNum, pageSize);
        String groupBy = type.equals(1) ? "m.grade" : "m.school_id";
        List<MyopiaClassProportionVO> vos = myopiaMapper.getAreaProportion(groupBy, newMission.getId());
        Map<String, String> schoolMap = getSchoolMap();
        vos.forEach(vo -> {
            String ratio = getRatio(vo.getHeadCount(), vo.getMyopiaCount());
            vo.setMyopiaRatio(ratio);
            String correctedRatio = getRatio(vo.getMyopiaCount(), vo.getCorrectedCount());
            vo.setCorrectedRatio(correctedRatio);
            vo.setSchoolName(schoolMap.get(vo.getSchoolId()));
            vo.setUncorrectedRatio((100 - Double.parseDouble(correctedRatio.replace("%", ""))) + "%");
        });
        return vos;
    }

    /**
     * 区域上传学校普查表
     *
     * @param
     * @return
     * @throws Exception
     */
    @Transactional
    public ResponseEntity importAreaFile(MultipartFile file) throws Exception {
        MyopiaExcelUtil<MyopiaErrorTemplate> util = new MyopiaExcelUtil<>(MyopiaErrorTemplate.class);
        // 从表格读取数据
        List<MyopiaErrorTemplate> lists = util.importExcel(file);
        //解析标题获取学校名和任务名
        Map<String, String> NameMap = parseTitle(util.getTitle());

        //匹配是否存在这个学校
        AreaSchoolRet school = getSchoolByName(NameMap.get("schoolName"));
        //创建任务
        MyopiaMission myopiaMission = createOrUpdateMyopiaMission(NameMap.get("missionName"));
        //校验模板
        util.checkTemplate();

        //查询学校所有学生
        Map<String, AreaStudentRet> studentMap = getAreaStudentMap(school.getId());


        Integer myopiaCount = 0;
        boolean flag = true;
        Set<Myopia> myopias = new HashSet<>();
        Set<MyopiaInfo> infos = new HashSet<>();

        //查询已存在学生
        List<Long> ids = myopiaMapper.getAllStudentId(school.getId());

        for (MyopiaErrorTemplate e : lists) {
            Myopia myopia = new Myopia();
            MyopiaInfo info = new MyopiaInfo();
            AreaStudentRet student = studentMap.get(e.getIdCardNo()) == null ?
                    studentMap.get(e.getStuCode()):studentMap.get(e.getIdCardNo());
            if (student == null) {
                e.setError("身份证和学籍id有误");
                flag = false;  // 设置标志为 false，表示后续不再更新
            }
            if (flag) {
                int okWear = e.getOkWearer().equals("是") ? 1 : 0;
                // 更新基本信息
                if (!ids.contains(student.getStudentId())){
//                    myopia.setGrade(student.getGradeName());
//                    myopia.setClassName(student.getClassName());
                    myopia.setGrade(e.getGrade());
                    myopia.setClassName(e.getClassName());
                    myopia.setClassId(student.getClassId());
                    myopia.setAge(e.getAge());
                    myopia.setSex(student.getSex());
                    myopia.setName(student.getName());
                    myopia.setStage(e.getStage());
                    myopia.setMyopiaLevel(e.getMyopiaLevel());
                    myopia.setRectifyMode(e.getRectifyMode());
                    myopia.setSchoolId(Long.valueOf(school.getId()));
                    myopia.setId(student.getStudentId());
                    myopia.setOkWearer(okWear);
                    myopias.add(myopia);
                }
                BeanUtils.copyProperties(e, info);
                info.setMyopiaId(myopia.getId());
                info.setMissionName(myopiaMission.getName());
                info.setSchoolId(Long.valueOf(school.getId()));
                info.setMissionId(myopiaMission.getId());
                info.setOkWearer(okWear);
                infos.add(info);
            }
            if (flag && !e.getMyopiaLevel().equals("未近视")) {
                myopiaCount++;
            }
        }
        if (!flag) {
            //存在错误导出数据
            myopiaMissionService.removeById(myopiaMission.getId());
            return util.exportExcelWorkbook(lists, "普查表", util.getTitle());
        }
        //删除本次任务多次上传，档案数据
        int delCount = infoMapper.delete(new LambdaQueryWrapper<MyopiaInfo>()
                .eq(MyopiaInfo::getMissionId, myopiaMission.getId())
                .eq(MyopiaInfo::getSchoolId, school.getId()));

        saveBatch(myopias);
        infoService.saveBatch(infos);
        //创建学校任务详情
        MyopiaSchoolMission schoolMission = schoolMissionService.getOne(new LambdaUpdateWrapper<MyopiaSchoolMission>()
                .eq(MyopiaSchoolMission::getMissionId, myopiaMission.getId())
                .eq(MyopiaSchoolMission::getSchoolId, school.getId()));
        if (ObjectUtils.isEmpty(schoolMission)){
            schoolMission = new MyopiaSchoolMission();
        }
        schoolMission.setStuCount(infos.size());
        schoolMission.setMyopiaNum(myopiaCount);
        schoolMission.setCensusStatus(1);
        schoolMissionService.updateById(schoolMission);
        //跟新任务
        myopiaMission.setStuCount(myopiaMission.getStuCount() + infos.size() - delCount);
        myopiaMissionService.updateById(checkStatus(myopiaMission, schoolMission,delCount == 0));
        return new ResponseEntity(AjaxResult.success(),HttpStatus.OK);
    }

    /**
     * 根据标题，获取学校名以及任务名
     *
     * @param title
     * @return
     */
    private Map<String, String> parseTitle(String title) {
        if (StringUtils.isEmpty(title) || !title.contains("）") || !title.contains("——")) {
            throw new ServiceException("标题异常");
        }

        String[] split = title.split("）");
        if (split.length < 2) {
            throw new ServiceException("标题异常");
        }

        String missionName = split[0].replace("（", "").replaceAll(" ", "");
        String schoolName = split[1].split("——")[0].replaceAll(" ", "");

        if (missionName.length() > 30) {
            throw new ServiceException("任务名不能大于30字符");
        }

        Map<String, String> titleMap = new HashMap<>();
        titleMap.put("missionName", missionName);
        titleMap.put("schoolName", schoolName);
        return titleMap;
    }


    /**
     * 通过名字获取学校
     *
     * @param schoolName
     * @return
     */
    private AreaSchoolRet getSchoolByName(String schoolName) {
        List<AreaSchoolRet> schools = authService.getSchool("area");
        AreaSchoolRet school = schools.stream().filter(e -> e.getName().equals(schoolName)).findFirst().orElse(null);
        if (ObjectUtils.isEmpty(school)) {
            throw new ServiceException("请确认上传文档标题'XXXX学校'替换为正确的学校名称");
        }
        return school;
    }

    /**
     * 创建任务
     *
     * @param missionName
     */
    private MyopiaMission createOrUpdateMyopiaMission(String missionName) {
        MyopiaMission myopiaMission = myopiaMissionService.getOne(new LambdaQueryWrapper<MyopiaMission>()
                .eq(MyopiaMission::getName, missionName)
                .eq(MyopiaMission::getDelFlag, 0));

        if (ObjectUtils.isEmpty(myopiaMission)) {
            myopiaMission = new MyopiaMission();
            myopiaMission.setName(missionName);
            myopiaMission.setAreaUp(1);
            myopiaMission.setEndTime(Date.from(LocalDate.now().atTime(LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant()));
            myopiaMissionService.createMission(myopiaMission);
        }
        return myopiaMission;
    }

    @Transactional
    public ResponseEntity importAreaRiskFile(MultipartFile file) throws Exception {
        MyopiaExcelUtil<MyopiaRiskErrorTemplate> util = new MyopiaExcelUtil<>(MyopiaRiskErrorTemplate.class);
        // 从表格读取数据
        List<MyopiaRiskErrorTemplate> lists = util.importExcel(file);
        //解析标题获取学校名和任务名
        Map<String, String> NameMap = parseTitle(util.getTitle());

        //匹配是否存在这个学校
        AreaSchoolRet school = getSchoolByName(NameMap.get("schoolName"));
        //创建任务
        MyopiaMission myopiaMission = createOrUpdateMyopiaMission(NameMap.get("missionName"));
        //校验模板
        util.checkTemplate();

        //查询学校所有学生
        Map<String, AreaStudentRet> studentMap = getAreaStudentMap(school.getId());

        Set<MyopiaRisk> risks = new HashSet<>();

        boolean flag = true;
        for (MyopiaRiskErrorTemplate e : lists) {
            AreaStudentRet student = studentMap.get(e.getIdCardNo()) == null ?
                    studentMap.get(e.getStuCode()):studentMap.get(e.getIdCardNo());
            if (student == null) {
                e.setError("身份信息错误或不存在");
                flag = false;  // 设置标志为 false，表示后续不再更新
            }
            if (flag) {
                MyopiaRisk risk = new MyopiaRisk();
                risk.setRiskLevel(e.getRiskLevel());
                risk.setMissionId(myopiaMission.getId());
                risk.setSchoolId(Long.valueOf(school.getId()));
                risk.setStuId(student.getStudentId());
                risk.setGrade(e.getGrade());
                risks.add(risk);
            }
        }
        if (!flag) {
            //存在错误导出数据
            myopiaMissionService.removeById(myopiaMission.getId());
            return util.exportExcelWorkbook(lists,"高危表", util.getTitle());
        }
        //删除本次任务多次上传，档案数据
        int delCount = myopiaRiskMapper.delete(new LambdaQueryWrapper<MyopiaRisk>()
                .eq(MyopiaRisk::getMissionId, myopiaMission.getId())
                .eq(MyopiaRisk::getSchoolId, school.getId()));
        riskService.saveBatch(risks);
        //更新学校任务详情
        MyopiaSchoolMission schoolMission = schoolMissionService.getOne(new LambdaUpdateWrapper<MyopiaSchoolMission>()
                .eq(MyopiaSchoolMission::getMissionId, myopiaMission.getId())
                .eq(MyopiaSchoolMission::getSchoolId, school.getId()));
        if (ObjectUtils.isEmpty(schoolMission)){
            schoolMission = new MyopiaSchoolMission();
        }
        schoolMission.setRiskNum(risks.size());
        schoolMission.setRiskStatus(1);
        schoolMissionService.updateById(schoolMission);
        //跟新任务
        myopiaMissionService.updateById(checkStatus(myopiaMission, schoolMission,delCount == 0));
        return new ResponseEntity(AjaxResult.success(),HttpStatus.OK);
    }

    /**
     * 普查表模板下载
     *
     * @return
     */
    public ResponseEntity getTemplate() {
        String schoolName = StringUtils.isNotBlank(SecurityUtils.getAuthInfo().getSchoolName()) ? SecurityUtils.getAuthInfo().getSchoolName():"XXXX";
        MyopiaExcelUtil<MyopiaTemplate> util = new MyopiaExcelUtil<>(MyopiaTemplate.class);
        ArrayList<MyopiaTemplate> list = new ArrayList<>();
        list.add(new MyopiaTemplate().setAge(17).setGrade("一年级").setStage("高中").setName("示例").setSex("男").setClassName("会计一班").setOkWearer("否").setRectifyMode("裸眼").setStuCode("415653").setIdCardNo("6532145687523321452")
                .setLEyeAxial(0.0).setREyeAxial(2.0).setLEyeRadius(1.0).setREyeRadius(2.0).setLNakedEyesight(4.0).setRNakedEyesight(4.0).setMyopiaLevel("低度近视").setLEyeCyl(1.0).setREyeCyl(2.0).setLRectifyEyesight(4.0).setRRectifyEyesight(4.0));
        return util.exportExcelWorkbook(list, "普查表", "（XXXX双流区儿童青少年近视防控普查）"+schoolName+"学校——普查结果");
    }

    public ResponseEntity getRiskTemplate() {
        String schoolName = StringUtils.isNotBlank(SecurityUtils.getAuthInfo().getSchoolName()) ? SecurityUtils.getAuthInfo().getSchoolName():"XXXX";
        MyopiaExcelUtil<MyopiaRiskTemplate> util = new MyopiaExcelUtil<>(MyopiaRiskTemplate.class);
        ArrayList<MyopiaRiskTemplate> list = new ArrayList<>();
        list.add(new MyopiaRiskTemplate().setName("示例").setGrade("一年级").setRiskLevel("近视高危").setStage("高中").setSex("男").setAge(16).setClassName("二班").setStuCode("12322").setIdCardNo("6452316532623652"));
        return util.exportExcelWorkbook(list, "高危表", "（XXXX双流区儿童青少年近视防控普查）"+schoolName+"学校——高危名单");
    }
}
